/* NOTICE
 
    Jim - the Java Image Manager, copyright (c) 2005 - 2007 Grant Gardner 
 
    Jim is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Jim is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  
    In addition, as a special exception, you are permitted to link this code
    with the 3rd party libraries required to compile this file and to
    distribute a linked combination including them. You must obey the
    GNU General Public License in all respects for all of the code except for
    those 3rd party libraries that are licenced under terms incompatible with the
    GNU General Public License.  
 
 
 NOTICE */

package au.com.lastweekend.jim.view;

import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.util.Arrays;
import java.util.Collection;

import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTree;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import org.apache.log4j.Logger;
import org.flexdock.docking.Dockable;
import org.flexdock.docking.DockableFactory;
import org.flexdock.docking.DockingConstants;
import org.flexdock.docking.DockingManager;
import org.flexdock.perspective.LayoutSequence;
import org.flexdock.perspective.Perspective;
import org.flexdock.perspective.PerspectiveFactory;
import org.flexdock.view.View;
import org.flexdock.view.Viewport;

import au.com.lastweekend.jim.model.ContactSheetListModel;
import au.com.lastweekend.jim.model.Keyword;
import au.com.lastweekend.jim.model.KeywordTreeModel;
import au.com.lastweekend.jim.model.MetadataTableModel;
import au.com.lastweekend.jim.swing.CloseableJTabbedPane;
import au.com.lastweekend.jim.swing.tree.TriStateTreeCellRenderer;
import au.com.lastweekend.jim.util.TriState;

/**
 * ViewPort containing all the dockable components for Jim
 * 
 * @version $Id: JimPort.java,v 1.10 2006/02/22 12:26:32 ggardner Exp $
 * @author <a href="mailto:grant@lastweekend.com.au"> <Grant Gardner> </a>
 */
public class JimViewPort extends Viewport implements DockableFactory, PerspectiveFactory {

    private static final long serialVersionUID = 1L;

    /**
     * @author ggardner
     *
     */
    private final class KeywordTreeCellRenderer extends TriStateTreeCellRenderer {

        private static final long serialVersionUID = 1L;

        @Override
        protected boolean getNodeEnabled(Object value) {

            Keyword keyword = (Keyword) value;
            return keyword.areKeywordsEnabled();

        }

        @Override
        protected TriState getNodeState(Object value) {

            Keyword keyword = (Keyword) value;
            return keyword.getSelectedState();
        }
    }

    public interface JimViewPortModel {

        MetadataTableModel getMetadataModel();

        KeywordTreeModel getKeywordTreeModel();

    }

    private static final Logger LOG = Logger.getLogger(JimViewPort.class);

    public static final String JP1 = "JP1";

    private static final String PREVIEW = "Preview";
    private static final String KEYWORDS = "Keywords";
    private static final String METADATA = "Metadata";
    private static final String SHEETTABS = "SheetTabs";
    private static final String SEARCH = "Search";

    private JTable exifTable;
    private JTree keywordTree;
    private ImagePanel previewPane;
    private CloseableJTabbedPane resultsPane;
    private SearchPanel searchPane;

    public JimViewPort(JimViewPortModel model) {

        // Build Components
        resultsPane = new CloseableJTabbedPane();

        ChangeListener tabSelectionListener = new ChangeListener() {

            public void stateChanged(ChangeEvent e) {

                               
                reSelect();
            }

        };
        resultsPane.addChangeListener(tabSelectionListener);

        previewPane = new ImagePanel();
        searchPane = new SearchPanel(model.getKeywordTreeModel());
        exifTable = new JTable(model.getMetadataModel());

        keywordTree = new JTree(model.getKeywordTreeModel());
        keywordTree.setRootVisible(false);
        keywordTree.setCellRenderer(new KeywordTreeCellRenderer());

    }

    public Dockable getDockable(String dockableId) {

        View v = null;
        if (SHEETTABS.equals(dockableId)) {
            v = makeView(resultsPane, SHEETTABS);
            v.setTitlebar(null);
            v.setTerritoryBlocked(DockingConstants.CENTER_REGION, true);

        } else if (METADATA.equals(dockableId)) {
            JScrollPane exifPane = new JScrollPane(exifTable);
            v = makeView(exifPane, METADATA);
        } else if (KEYWORDS.equals(dockableId)) {
            v = makeView(new JScrollPane(keywordTree), KEYWORDS);
        } else if (PREVIEW.equals(dockableId)) {
            v = makeView(previewPane, PREVIEW);
        } else if (SEARCH.equals(dockableId)) {
            v = makeView(new JScrollPane(searchPane), SEARCH);
        }
        return v;
    }

    public Perspective getPerspective(String persistentId) {

        if (persistentId.equals(JP1)) {
            Perspective p = new Perspective(JP1, "Jim Perspective");
            LayoutSequence s = p.getInitialSequence(true);

            s.add(SHEETTABS);
            s.add(METADATA, SHEETTABS, DockingConstants.EAST_REGION, 0.5f);
            s.add(PREVIEW, SHEETTABS, DockingConstants.SOUTH_REGION, 0.5f);
            s.add(KEYWORDS, METADATA);
            s.add(SEARCH, METADATA);
            return p;
        } else {
            return null;
        }
    }

    private View makeView(Container comp, String desc) {

        View v = new View(desc, desc);
        v.setContentPane(comp);
        return v;
    }

    public ContactSheet getActiveContactSheet() {

        return (ContactSheet) resultsPane.getSelectedComponent();
    }

    public Component getDockableComponent(String dockableId) {

        return (Component) getDockable(dockableId);
    }

    public ContactSheet openContactSheet(ContactSheetListModel model) {

        ContactSheet newContactSheet;
        newContactSheet = new ContactSheet(model);
        resultsPane.addTab(model.getName(), newContactSheet);
        resultsPane.setSelectedComponent(newContactSheet);
        LOG.info(resultsPane.getSize());
        return newContactSheet;
    }

    public void setPreferredSize(Dimension preferredSize) {

        // Drive the initial sizing from the resultsPane
        resultsPane.setPreferredSize(preferredSize);
    }

    public Collection<ContactSheet> getContactSheets() {

        Component[] components = resultsPane.getComponents();
        ContactSheet[] sheets = new ContactSheet[components.length];
        System.arraycopy(components, 0, sheets, 0, components.length);
        return Arrays.asList(sheets);
    }

    public SearchPanel getSearchPanel() {

        return searchPane;
    }

    /**
     * @return
     */
    public JTree getKeywordTree() {

        return keywordTree;
    }

    /**
     * @return
     */
    public ImagePanel getImagePanel() {

        return previewPane;
    }

    /**
     * @param previewTitle
     */
    public void setPreviewTitle(String previewTitle) {

        Dockable preview = DockingManager.getDockable(PREVIEW);
        if (preview != null) {
            View v = (View) preview;
            v.setTitle(previewTitle);
            v.getTitlebar().repaint();
        }

    }

    public void reSelect() {

        if (resultsPane.getSelectedComponent() instanceof ContactSheet) {
            ContactSheet selectedSheet = (ContactSheet) resultsPane.getSelectedComponent();
            JList viewList = selectedSheet.getViewList();
            // Redo the selection.
            // This way the same list selection listener can be added
            // to each contact sheet and will be notified on tab changes as well.
            viewList.setSelectedIndices(viewList.getSelectedIndices());
        }
    }
}